package cz.muni.fi.pa165.soccergamesarchive.persistencelayer.entities;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Temporal;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;

/**
 *
 * @author Ondrej Dubovec
 */
@Entity
@NamedQueries({
    @NamedQuery(name = "SoccerMatch.findByTeamID",
                query = "SELECT m "
                + "FROM SoccerMatch m "
                + "WHERE m.homeTeam.id = :id OR m.awayTeam.id = :id "),
    @NamedQuery(name = "SoccerMatch.getSoccerMatchByDate",
                query = "SELECT m "
                + "FROM SoccerMatch m "
                + "WHERE cast(m.matchDate as date) = :soccerMatchDate")
})

public class SoccerMatch implements Serializable {

    private static final long serialVersionUID = 2L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Temporal(javax.persistence.TemporalType.TIMESTAMP)
    @Column(nullable = false)
    private Date matchDate;

    @Column(length = 40, nullable = false)
    private String stadiumName;

    @OneToMany(mappedBy = "soccerMatch", orphanRemoval = true,
               cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @Fetch(FetchMode.SUBSELECT)
    private List<Goal> goals = new ArrayList<>();

    @ManyToOne
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JoinColumn(nullable = false)
    private Team homeTeam;

    @ManyToOne
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JoinColumn(nullable = false)
    private Team awayTeam;

    public SoccerMatch() {
    }

    public SoccerMatch(Date matchDate, String stadiumName, Team homeTeam,
                       Team awayTeam) {
        this.matchDate = matchDate;
        this.stadiumName = stadiumName;
        this.homeTeam = homeTeam;
        this.awayTeam = awayTeam;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Date getMatchDate() {
        return this.matchDate;
    }

    public void setMatchDate(Date matchDate) {
        this.matchDate = matchDate;
    }

    public String getStadiumName() {
        return stadiumName;
    }

    public void setStadiumName(String stadiumName) {
        this.stadiumName = stadiumName;
    }

    public List<Goal> getGoals() {
        return this.goals;
    }

    public void setGoals(List<Goal> goals) {
        this.goals = goals;
    }

    public Team getHomeTeam() {
        return this.homeTeam;
    }

    public void setHomeTeam(Team homeTeam) {
        this.homeTeam = homeTeam;
    }

    public Team getAwayTeam() {
        return this.awayTeam;
    }

    public void setAwayTeam(Team awayTeam) {
        this.awayTeam = awayTeam;
    }

    @Override
    public int hashCode() {
        int hash = (this.id == null) ? 0 : this.id.hashCode();
        return 79 * hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof SoccerMatch)) {
            return false;
        }
        final SoccerMatch other = (SoccerMatch) obj;

        if (this.id == null && other.id == null) {
            if (!isEqual(this.matchDate, other.matchDate)) {
                return false;
            }

            if (!isEqual(this.awayTeam, other.awayTeam)) {
                return false;
            }

            if (!isEqual(this.homeTeam, other.homeTeam)) {
                return false;
            }

            if (!isEqual(this.stadiumName, other.stadiumName)) {
                return false;
            }
        }

        return (this.id != null || other.id == null) && (this.id == null
                || this.id
                .equals(
                        other.id));
    }

    private static boolean isEqual(Object expected, Object actual) {
        if ((expected == null && actual != null) || (expected != null && actual
                == null)) {
            return false;
        }

        return expected == null || expected.equals(actual);
    }

    @Override
    public String toString() {
        return "SoccerMatch{" + "id=" + id + ", matchDate=" + matchDate
                + ", stadiumName=" + stadiumName + '}';
    }

}
